package com.ali.common;

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class QRCodeUtil {

    /**
     * 生成二维码
     */
    public static String encode(String content, String path) {
        BitMatrix bitMatrix;
        try {
            QRCodeWriter qrCodeWriter = new QRCodeWriter();

            Map<EncodeHintType, Object> hints = new HashMap<>();
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.Q);
            hints.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);

            bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, 500, 500, hints);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        if (path != null && !path.isEmpty()) {
            saveImageFile(bitMatrix, path);
        } else {
            return getImageUrl(bitMatrix);
        }

        return "";
    }

    /**
     * 生成图片文件
     */
    private static void saveImageFile(BitMatrix bitMatrix, String path) {
        try {
            File file = new File(path);
            MatrixToImageWriter.writeToPath(bitMatrix, "PNG", file.toPath());
        } catch (Exception e) {
            e.fillInStackTrace();
        }
    }

    /**
     * 生成图片Url
     */
    private static String getImageUrl(BitMatrix bitMatrix) {
        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
            MatrixToImageWriter.writeToStream(bitMatrix, "PNG", byteArrayOutputStream);

            String imageUrl = Base64.encodeBase64String(byteArrayOutputStream.toByteArray());
            log.info("imageUrl：" + imageUrl);
            imageUrl = imageUrl.replaceAll("\r\n", "");
            log.info("imageUrl：" + imageUrl);
            imageUrl = "data:image/png;base64," + imageUrl;
            log.info("imageUrl：" + imageUrl);
            return imageUrl;
        } catch (Throwable e) {
            e.fillInStackTrace();
        }

        return "";
    }

    /**
     * 解析二维码
     */
    public static String decode(String path) {
        BufferedImage bufferedImage;
        Result result;
        try {
            MultiFormatReader multiFormatReader = new MultiFormatReader();

            File file = new File(path);
            bufferedImage = ImageIO.read(file);
            LuminanceSource luminanceSource = new BufferedImageLuminanceSource(bufferedImage);
            HybridBinarizer hybridBinarizer = new HybridBinarizer(luminanceSource);
            BinaryBitmap binaryBitmap = new BinaryBitmap(hybridBinarizer);

            Map<DecodeHintType, Object> hints = new HashMap<>();
            hints.put(DecodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);

            result = multiFormatReader.decode(binaryBitmap, hints);
            return result.getText();
        } catch (Exception e) {
            e.fillInStackTrace();
        }

        return "";
    }
}